﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "SectionViewSymbolNew.h"
#include "SectionViewSymbolNewBehaviors.h"

#include "NdbObjectSchematic.h"
#include "DbObjectUtils.h"
#include "OwnerPtr.h"
#include "IGenericElement.h"
#include "IElementBasicInformation.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "IElementParentReporter.h"
#include "IGraphicsElementShape.h"
#include "IModelView.h"
#include "IViewClipRange.h"
#include "IDocument.h"
#include "Vector3d.h"
#include "AlgorithmProject.h"
#include "IPlane.h"
#include "IGraphicsLine.h"
#include "IGraphicsText.h"
#include "Vector3dUtils.h"
#include "AnchorAlignmentType.h"
#include "TextPrimitiveType.h"
#include "AlgorithmMinimalDistance.h"
#include "Vector2dUtils.h"
#include "MathUtils.h"
#include "IModelViewEventArgs.h"
#include "IModelViewEvent.h"
#include "IElementPositionPoints.h"
#include "IRegeneratorDataIdCreator.h"
#include "IRegenerator.h"
#include "IElementParameters.h"
#include "IGraphicsStyleManager.h"
#include "GbmpModelViewUtil.h"
#include "ImplementationUidTreeRegister.h"
#include "NdbUpgrade.h"
#include "NdbDocUpgradeManager.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"



using namespace gcmp;

const double SectionViewSymbolLongLineLength = 1000;
const double SectionViewSymbolShortLineLength = 600;
const double SectionViewSymbolNewFontsHeight = 514;  //由于GText替换为GTextEx后会导致字形显示变大，此处为了基本达到原有的大小*0.735,700*0.735,此处的0.735为经验值

IMPLEMENT_REGEN_FUNCTIONS(gcmp, SectionViewSymbolNew, SectionViewCoord)

BEGIN_UPGRADE_CLASS(gcmp, SectionViewSymbolNew, 2)
ADD_NON_OBJECT_PROPERTY(Coordinate3d, SectionViewCoord)
END_UPGRADE_CLASS

/*
*一个modelview对应一个ElementChangeMarker 和  GraphicsNodeSpecificStyleAndMaterialByTag 对象，如果老文件没有此对象，则创建
*/
void DocUpgradeSectionViewSymbolCoordinateByModelView(void *pVoid)
{
    gcmp::IDocument* pDoc = static_cast<gcmp::IDocument*>(pVoid);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    std::vector<gcmp::IElement*> pElements = pDoc->GetAllElements();
    FOR_EACH(pElement, pElements)
    {
        IGenericElement* pGenericElement = quick_cast<IGenericElement>(pElement);
        if (pGenericElement)
        {
            SectionViewSymbolNew* pSectionViewSymbol = quick_cast<SectionViewSymbolNew>(pGenericElement->GetExternalObject());
            if (pSectionViewSymbol)
            {
                const IModelView* pModelView = quick_cast<IModelView>(pDoc->GetElement(pSectionViewSymbol->GetModelViewId()));
                DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"所属ModelView为空",L"GDMPLab",L"2024-03-30");

                Vector3d viewOriginPt = pModelView->GetOrigin();
                Vector3d viewDir = pModelView->GetViewDirection();
                Vector3d xDir = pModelView->GetRightDirection();
                Vector3d yDir = pModelView->GetUpDirection();

                Vector3d originPt = (viewOriginPt*viewDir)*viewDir;
                Coordinate3d coord = Coordinate3d(originPt, xDir, yDir);
                pSectionViewSymbol->SetSectionViewCoord(coord);
            }
        }
    }
}

const Guid s_idOfDocUpgradeSectionViewSymbolCoordinateByModelView = { 0x7e26909e, 0x34bf, 0x43f3,{ 0xa7, 0x55, 0x64, 0x86, 0xde, 0x85, 0xd0, 0xe7 } };

DEFINE_DOC_UPGRADER_BEGIN(s_idOfDocUpgradeSectionViewSymbolCoordinateByModelView, 给剖切符号添加定位坐标系, DocUpgradeSectionViewSymbolCoordinateByModelView);
DEFINE_DOC_UPGRADER_END();

namespace {

    class AssociatedModelViewEventHandler : public IModelViewEventHandler
    {
    public:
        AssociatedModelViewEventHandler(SectionViewSymbolNew* pViewSymbol)
            : m_pViewSymbol(pViewSymbol)
        {
        }

        ~AssociatedModelViewEventHandler()
        {
        }

        virtual void On(IModelViewEventArgs* pArgs) override
        {
            if (!pArgs || !m_pViewSymbol || !m_pViewSymbol->GetDocument())
                return;

            if (pArgs->GetType() == ModelViewEventType::NameChanged)
            {
                bool bMatch = (m_pViewSymbol->GetDocument()->GetRuntimeId() == pArgs->GetDocumentRuntimeId() &&
                    m_pViewSymbol->GetModelViewId() == pArgs->GetModelViewId());
                DBG_WARN_AND_RETURN_VOID_UNLESS(bMatch, L"事件不参数不匹配",L"GDMPLab",L"2024-03-30");

                const IModelView* pModelView = quick_cast<const IModelView>(m_pViewSymbol->GetDocument()->GetElement(m_pViewSymbol->GetModelViewId()));
                DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

                m_pViewSymbol->MarkChanged();
            }
        }
    private:
        SectionViewSymbolNew* m_pViewSymbol;
    };
}

namespace gcmp {

    // 剖面视图标志的控制点行为
    class SectionViewSymbolNewPositionPoints : public NdbObjectSchematic, public IElementPositionPoints
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, SectionViewSymbolNewPositionPoints, gcmp::NdbObjectSchematic, A6EE0E03 - BCE8 - 438A - 9EEF - EFC2DA3B87C8, gbmpmodel, gcmp::IElementPositionPoints)
            DATA(OwnerPtr<IElementPositionPoints>, DefaultPositonPoints)
            DATA_TRANSIENT(IElement*, pOwnerElement)
            DBOBJECT_DATA_END

    public:
        SectionViewSymbolNewPositionPoints(IElement* pElement)
        {
            m_pOwnerElement = pElement;
            SetDefaultPositonPoints__(IElementPositionPoints::CreateBaseOnElementPosition(pElement));
        }

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

#pragma region IElementPositionPoints 接口
    public:
        virtual int GetControlPointCount() const override
        {
            const IElementPositionPoints* pDefaultPositonPoints = GetDefaultPositonPoints();
            DBG_WARN_AND_RETURN_UNLESS(pDefaultPositonPoints, 0, L"invalid pDefaultPositonPoints",L"GDMPLab",L"2024-03-30");
            return pDefaultPositonPoints->GetControlPointCount();
        }
        virtual RegenDataId GetControlPointRdId(int index) const override
        {
            const IElementPositionPoints* pDefaultPositonPoints = GetDefaultPositonPoints();
            DBG_WARN_AND_RETURN_UNLESS(pDefaultPositonPoints, RegenDataId(), L"invalid pDefaultPositonPoints",L"GDMPLab",L"2024-03-30");
            return pDefaultPositonPoints->GetControlPointRdId(index);
        }
        virtual void MarkControlPointRdId(int index) override
        {
            IElementPositionPoints* pDefaultPositonPoints = GetDefaultPositonPoints();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDefaultPositonPoints, L"invalid pDefaultPositonPoints",L"GDMPLab",L"2024-03-30");
            return pDefaultPositonPoints->MarkControlPointRdId(index);
        }
        virtual bool SetOwnerElement(IElement* pOwnerElement) override
        {
            IElementPositionPoints* pDefaultPositonPoints = GetDefaultPositonPoints();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pDefaultPositonPoints, L"invalid pDefaultPositonPoints",L"GDMPLab",L"2024-03-30");
            return pDefaultPositonPoints->SetOwnerElement(pOwnerElement);
        }
        virtual IElement* GetOwnerElement() override
        {
            IElementPositionPoints* pDefaultPositonPoints = GetDefaultPositonPoints();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDefaultPositonPoints, L"invalid pDefaultPositonPoints",L"GDMPLab",L"2024-03-30");
            return pDefaultPositonPoints->GetOwnerElement();
        }
        virtual const IElement* GetOwnerElement() const override
        {
            const IElementPositionPoints* pDefaultPositonPoints = GetDefaultPositonPoints();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDefaultPositonPoints, L"invalid pDefaultPositonPoints",L"GDMPLab",L"2024-03-30");
            return pDefaultPositonPoints->GetOwnerElement();
        }

        virtual Vector3d GetControlPoint(int pointIndex) const override
        {
            Vector3d ret = Vector3d::Zero;

            Vector3d sectionViewPoint;
            Vector3d sectionViewRightDir;
            Vector3d sectionViewUpDir;
            Vector3d sectionViewDir;
            bool bOk = GetSectionModelViewPositionInfo(sectionViewPoint, sectionViewRightDir, sectionViewUpDir, sectionViewDir);
            DBG_WARN_AND_RETURN_UNLESS(bOk, ret, L"Fail to get SectionModelViewPositionInfo",L"GDMPLab",L"2024-03-30");

            double viewPortLeftOffset = 0;
            double viewPortRightOffset = 0;
            double viewPortUpOffset = 0;
            double viewPortDownOffset = 0;
            double viewBottomOffset = 0;
            bOk = GetSectionModelViewOffsetInfo(viewPortLeftOffset, viewPortRightOffset, viewPortUpOffset, viewPortDownOffset, viewBottomOffset);
            DBG_WARN_AND_RETURN_UNLESS(bOk, ret, L"Fail to get SectionModelViewOffsetInfo",L"GDMPLab",L"2024-03-30");

            const SectionViewSymbolNew* pSymbol = GetSectionSymbol();
            DBG_WARN_AND_RETURN_UNLESS(pSymbol, ret, L"Fail to get SectionSymbol",L"GDMPLab",L"2024-03-30");

            SectionViewSymbolNewAuxiliaryType pointType = (SectionViewSymbolNewAuxiliaryType)pointIndex;
            switch (pointType)
            {
            case SectionViewSymbolNewAuxiliaryType::BoxLeftPlanePointType:
            {
                ret = sectionViewPoint + (-sectionViewRightDir) * viewPortLeftOffset + sectionViewUpDir * (viewPortUpOffset - viewPortDownOffset) / 2.0 + sectionViewDir * (viewBottomOffset / 2.0);
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxRightPlanePointType:
            {
                ret = sectionViewPoint + sectionViewRightDir * viewPortRightOffset + sectionViewUpDir * (viewPortUpOffset - viewPortDownOffset) / 2.0 + sectionViewDir * (viewBottomOffset / 2.0);
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxUpPlanePointType:
            {
                ret = sectionViewPoint + sectionViewUpDir * viewPortUpOffset + sectionViewRightDir * (viewPortRightOffset - viewPortLeftOffset) / 2.0 + sectionViewDir * (viewBottomOffset / 2.0);
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxDownPlanePointType:
            {
                ret = sectionViewPoint + (-sectionViewUpDir) * viewPortDownOffset + sectionViewRightDir * (viewPortRightOffset - viewPortLeftOffset) / 2.0 + sectionViewDir * (viewBottomOffset / 2.0);
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxSectionPlanePointType:
            {
                ret = sectionViewPoint + sectionViewRightDir * (viewPortRightOffset - viewPortLeftOffset) / 2.0 + sectionViewUpDir * (viewPortUpOffset - viewPortDownOffset) / 2.0;
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxBottomPlanePointType:
            {
                ret = sectionViewPoint + sectionViewRightDir * (viewPortRightOffset - viewPortLeftOffset) / 2.0 + sectionViewUpDir * (viewPortUpOffset - viewPortDownOffset) / 2.0 + sectionViewDir * viewBottomOffset;
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::SymbolLeftPointType:
            {
                ret = sectionViewPoint + (-sectionViewRightDir) * pSymbol->GetSymbolLeftPtOffset();
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::SymbolRightPointType:
            {
                ret = sectionViewPoint + sectionViewRightDir * pSymbol->GetSymbolRightPtOffset();
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::SymbolUpPointType:
            {
                ret = sectionViewPoint + sectionViewUpDir * pSymbol->GetSymbolUpPtOffset();
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::SymbolDownPointType:
            {
                ret = sectionViewPoint + (-sectionViewUpDir) * pSymbol->GetSymbolDownPtOffset();
                break;
            }
            default:
                break;
            }
            return ret;
        }

        virtual void SetControlPoint(int pointIndex, const Vector3d& pos) override
        {
            IModelView* pSectionModelView = GetSectionModelViewOfOwnerSymbol();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pSectionModelView, L"invalid pSectionModelView",L"GDMPLab",L"2024-03-30");
            IViewClipRange* pViewClipRange = IViewClipRange::GetViewClipRange(pSectionModelView->GetDocument(), pSectionModelView->GetViewClipRangeId());
            Vector3d sectionViewPoint;
            Vector3d sectionViewRightDir;
            Vector3d sectionViewUpDir;
            Vector3d sectionViewDir;
            bool bOk = GetSectionModelViewPositionInfo(sectionViewPoint, sectionViewRightDir, sectionViewUpDir, sectionViewDir);
            DBG_WARN_AND_RETURN_VOID_UNLESS(bOk, L"Fail to get SectionModelViewPositionInfo",L"GDMPLab",L"2024-03-30");

            double sectionViewPortLeftOffset = 0;
            double sectionViewPortRightOffset = 0;
            double sectionViewPortUpOffset = 0;
            double sectionViewPortDownOffset = 0;
            double sectionViewBottomOffset = 0;
            bOk = GetSectionModelViewOffsetInfo(sectionViewPortLeftOffset, sectionViewPortRightOffset, sectionViewPortUpOffset, sectionViewPortDownOffset, sectionViewBottomOffset);
            DBG_WARN_AND_RETURN_VOID_UNLESS(bOk, L"Fail to get SectionModelViewOffsetInfo",L"GDMPLab",L"2024-03-30");

            Vector3d ctrlPointPos = GetControlPoint(pointIndex);
            SectionViewSymbolNewAuxiliaryType pointType = (SectionViewSymbolNewAuxiliaryType)pointIndex;
            switch (pointType)
            {
            case SectionViewSymbolNewAuxiliaryType::BoxSectionPlanePointType:
            {
                //判断移动方向是否与剖面视图方向同侧
                bool bSameSide = MathUtils::IsGreaterThan(sectionViewDir.Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时剖面平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewDir);

                if (bSameSide && MathUtils::IsGreaterThan(moveDistance, sectionViewBottomOffset))
                {
                    moveDistance = sectionViewBottomOffset;
                }

                pSectionModelView->SetOrigin(sectionViewPoint + moveDistance * sectionViewDir * (bSameSide ? 1 : -1));
                pSectionModelView->UpdateBottomPlane(sectionViewBottomOffset + moveDistance * (bSameSide ? -1 : 1));
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxLeftPlanePointType:
            {
                //判断移动方向是否与剖面视图右方向同侧
                bool bSameSide = MathUtils::IsGreaterThan(sectionViewRightDir.Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时左平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewRightDir);

                if (bSameSide && MathUtils::IsGreaterThan(moveDistance, sectionViewPortLeftOffset + sectionViewPortRightOffset))
                {
                    moveDistance = sectionViewPortLeftOffset + sectionViewPortRightOffset;
                }

                sectionViewPortLeftOffset = sectionViewPortLeftOffset + moveDistance * (bSameSide ? -1 : 1);
                pViewClipRange->UpdateRectViewClipRange(sectionViewPortLeftOffset, sectionViewPortRightOffset, sectionViewPortUpOffset, sectionViewPortDownOffset);
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxRightPlanePointType:
            {
                //判断移动方向是否与剖面视图右方向同侧
                bool bSameSide = MathUtils::IsGreaterThan(sectionViewRightDir.Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时右平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewRightDir);

                if (!bSameSide && MathUtils::IsGreaterThan(moveDistance, sectionViewPortLeftOffset + sectionViewPortRightOffset))
                {
                    moveDistance = sectionViewPortLeftOffset + sectionViewPortRightOffset;
                }

                sectionViewPortRightOffset = sectionViewPortRightOffset + moveDistance * (bSameSide ? 1 : -1);
                pViewClipRange->UpdateRectViewClipRange(sectionViewPortLeftOffset, sectionViewPortRightOffset, sectionViewPortUpOffset, sectionViewPortDownOffset);
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxBottomPlanePointType:
            {
                //判断移动方向是否与剖面视图方向同侧
                bool bSameSide = MathUtils::IsGreaterThan(sectionViewDir.Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时深度平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewDir);

                if (!bSameSide && MathUtils::IsGreaterThan(moveDistance, sectionViewBottomOffset))
                {
                    moveDistance = sectionViewBottomOffset;
                }

                pSectionModelView->UpdateBottomPlane(sectionViewBottomOffset + moveDistance * (bSameSide ? 1 : -1));
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxUpPlanePointType:
            {
                //判断移动方向是否与剖面视图上方向同侧
                bool bSameSide = MathUtils::IsGreaterThan(sectionViewUpDir.Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时上表面平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewUpDir);

                if (!bSameSide && MathUtils::IsGreaterThan(moveDistance, sectionViewPortUpOffset + sectionViewPortDownOffset))
                {
                    moveDistance = sectionViewPortUpOffset + sectionViewPortDownOffset;
                }

                sectionViewPortUpOffset = sectionViewPortUpOffset + moveDistance * (bSameSide ? 1 : -1);
                pViewClipRange->UpdateRectViewClipRange(sectionViewPortLeftOffset, sectionViewPortRightOffset, sectionViewPortUpOffset, sectionViewPortDownOffset);
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::BoxDownPlanePointType:
            {
                //判断移动方向是否与剖面视图上方向同侧
                bool bSameSide = MathUtils::IsGreaterThan(sectionViewUpDir.Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时下表面平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewUpDir);

                if (bSameSide && MathUtils::IsGreaterThan(moveDistance, sectionViewPortUpOffset + sectionViewPortDownOffset))
                {
                    moveDistance = sectionViewPortUpOffset + sectionViewPortDownOffset;
                }

                sectionViewPortDownOffset = sectionViewPortDownOffset + moveDistance * (bSameSide ? -1 : 1);
                pViewClipRange->UpdateRectViewClipRange(sectionViewPortLeftOffset, sectionViewPortRightOffset, sectionViewPortUpOffset, sectionViewPortDownOffset);
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::SymbolLeftPointType:
            {
                SectionViewSymbolNew* pSymbol = GetSectionSymbol();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pSymbol, L"invalid pSymbol",L"GDMPLab",L"2024-03-30");
                double symbolLeftPtOffset = pSymbol->GetSymbolLeftPtOffset();
                double symbolRightPtOffset = pSymbol->GetSymbolRightPtOffset();

                //判断移动方向是否与剖面视图 左 方向同侧
                bool bSameSide = MathUtils::IsGreaterThan((-sectionViewRightDir).Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时左平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewRightDir);

                if (!bSameSide && MathUtils::IsGreaterThan(moveDistance, symbolLeftPtOffset + symbolRightPtOffset - SectionViewSymbolLongLineLength * 2))
                {
                    moveDistance = symbolLeftPtOffset + symbolRightPtOffset - SectionViewSymbolLongLineLength * 2;
                }

                pSymbol->SetSymbolLeftPtOffset(symbolLeftPtOffset + moveDistance * (bSameSide ? 1 : -1));
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::SymbolRightPointType:
            {
                SectionViewSymbolNew* pSymbol = GetSectionSymbol();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pSymbol, L"invalid pSymbol",L"GDMPLab",L"2024-03-30");
                double symbolLeftPtOffset = pSymbol->GetSymbolLeftPtOffset();
                double symbolRightPtOffset = pSymbol->GetSymbolRightPtOffset();

                //判断移动方向是否与剖面视图 右 方向同侧
                bool bSameSide = MathUtils::IsGreaterThan(sectionViewRightDir.Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时右平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewRightDir);

                if (!bSameSide && MathUtils::IsGreaterThan(moveDistance, symbolLeftPtOffset + symbolRightPtOffset - SectionViewSymbolLongLineLength * 2))
                {
                    moveDistance = symbolLeftPtOffset + symbolRightPtOffset - SectionViewSymbolLongLineLength * 2;
                }

                pSymbol->SetSymbolRightPtOffset(symbolRightPtOffset + moveDistance * (bSameSide ? 1 : -1));
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::SymbolUpPointType:
            {
                SectionViewSymbolNew* pSymbol = GetSectionSymbol();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pSymbol, L"invalid pSymbol",L"GDMPLab",L"2024-03-30");
                double symbolUpPtOffset = pSymbol->GetSymbolUpPtOffset();
                double symbolDownPtOffset = pSymbol->GetSymbolDownPtOffset();

                //判断移动方向是否与剖面视图 上 方向同侧
                bool bSameSide = MathUtils::IsGreaterThan(sectionViewUpDir.Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时上表面平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewUpDir);

                if (!bSameSide && MathUtils::IsGreaterThan(moveDistance, symbolUpPtOffset + symbolDownPtOffset - SectionViewSymbolLongLineLength * 2))
                {
                    moveDistance = symbolUpPtOffset + symbolDownPtOffset - SectionViewSymbolLongLineLength * 2;
                }

                pSymbol->SetSymbolUpPtOffset(symbolUpPtOffset + moveDistance * (bSameSide ? 1 : -1));
                break;
            }
            case SectionViewSymbolNewAuxiliaryType::SymbolDownPointType:
            {
                SectionViewSymbolNew* pSymbol = GetSectionSymbol();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pSymbol, L"invalid pSymbol",L"GDMPLab",L"2024-03-30");
                double symbolUpPtOffset = pSymbol->GetSymbolUpPtOffset();
                double symbolDownPtOffset = pSymbol->GetSymbolDownPtOffset();

                //判断移动方向是否与剖面视图 下 方向同侧
                bool bSameSide = MathUtils::IsGreaterThan((-sectionViewUpDir).Dot(pos - ctrlPointPos), 0, Constants::FLOAT_EPS);

                //创建临时下表面平面，求pos到该平面的距离
                double moveDistance = GetPointToPlaneDistance(pos, ctrlPointPos, sectionViewUpDir);

                if (!bSameSide && MathUtils::IsGreaterThan(moveDistance, symbolUpPtOffset + symbolDownPtOffset - SectionViewSymbolLongLineLength * 2))
                {
                    moveDistance = symbolUpPtOffset + symbolDownPtOffset - SectionViewSymbolLongLineLength * 2;
                }

                pSymbol->SetSymbolDownPtOffset(symbolDownPtOffset + moveDistance * (bSameSide ? 1 : -1));
                break;
            }
            default:
                break;
            }
        }

#pragma endregion IElementPositionPoints 接口

#pragma region Inner Tools
    private:
        IElementPositionPoints* GetDefaultPositonPoints()
        {
            return GetDefaultPositonPointsFW__().get();
        }

        const IElementPositionPoints* GetDefaultPositonPoints() const
        {
            return GetDefaultPositonPoints__().get();
        }

        const SectionViewSymbolNew* GetSectionSymbol() const
        {
            const IGenericElement* pOwnerElement = quick_cast<IGenericElement>(GetOwnerElement());
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pOwnerElement, L"invalid pOwnerElement",L"GDMPLab",L"2024-03-30");
            return quick_cast<SectionViewSymbolNew>(pOwnerElement->GetExternalObject());
        }

        SectionViewSymbolNew* GetSectionSymbol()
        {
            IGenericElement* pOwnerElement = quick_cast<IGenericElement>(GetOwnerElement());
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pOwnerElement, L"invalid pOwnerElement",L"GDMPLab",L"2024-03-30");
            return quick_cast<SectionViewSymbolNew>(pOwnerElement->GetExternalObject());
        }

        IModelView* GetSectionModelViewOfOwnerSymbol() const
        {
            const SectionViewSymbolNew* pSymbol = GetSectionSymbol();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSymbol, L"invalid pSymbol",L"GDMPLab",L"2024-03-30");
            return pSymbol->GetSectionModelView();
        }

        bool GetSectionModelViewPositionInfo(Vector3d& sectionViewPoint, Vector3d& sectionViewRightDir, Vector3d& sectionViewUpDir, Vector3d& sectionViewDir) const
        {
            IModelView* pSectionModelView = GetSectionModelViewOfOwnerSymbol();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pSectionModelView, L"invalid pSectionModelView",L"GDMPLab",L"2024-03-30");

            sectionViewPoint = pSectionModelView->GetOrigin();
            sectionViewRightDir = pSectionModelView->GetRightDirection();
            sectionViewUpDir = pSectionModelView->GetUpDirection();
            sectionViewDir = pSectionModelView->GetViewDirection();
            sectionViewRightDir.Normalize();
            sectionViewUpDir.Normalize();
            sectionViewDir.Normalize();

            return true;
        }

        bool GetSectionModelViewOffsetInfo(double& sectionViewPortLeftOffset, double& sectionViewPortRightOffset, double& sectionViewPortUpOffset, double& sectionViewPortDownOffset, double& sectionViewBottomOffset) const
        {
            IModelView* pSectionModelView = GetSectionModelViewOfOwnerSymbol();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pSectionModelView, L"invalid pSectionModelView",L"GDMPLab",L"2024-03-30");
            IViewClipRange* pViewClipRange = IViewClipRange::GetViewClipRange(pSectionModelView->GetDocument(), pSectionModelView->GetViewClipRangeId());
            bool bOk = pViewClipRange->GetRectViewClipRange(sectionViewPortLeftOffset, sectionViewPortRightOffset, sectionViewPortUpOffset, sectionViewPortDownOffset);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"Fail to get DefaultRectViewport",L"GDMPLab",L"2024-03-30");
            bOk = pSectionModelView->GetBottomPlaneOffset(sectionViewBottomOffset);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"Fail to get BottomOffset",L"GDMPLab",L"2024-03-30");

            return bOk;
        }

        double GetPointToPlaneDistance(const Vector3d& point, const Vector3d& pointOnPlane, const Vector3d& planeDirection)
        {
            OwnerPtr<IPlane> opTmpPlane = IPlane::Create(pointOnPlane, planeDirection);
            DBG_WARN_AND_RETURN_UNLESS(opTmpPlane, 0, L"invalid opTmpPlane",L"GDMPLab",L"2024-03-30");

            Vector3d pointProjectedOnPlane;
            Vector2d uvParameter;
            bool bOk = AlgorithmProject::Project(point, opTmpPlane.get(), uvParameter, pointProjectedOnPlane);
            DBG_WARN_AND_RETURN_UNLESS(bOk, 0, L"fail to project",L"GDMPLab",L"2024-03-30");

            return Vector3dUtils::Distance(pointProjectedOnPlane, point);
        }
#pragma endregion Inner Tools
    };
    DBOBJECT_DATA_DEFINE(SectionViewSymbolNewPositionPoints)
    {
        m_pOwnerElement = nullptr;
        SetDefaultPositonPoints__(nullptr);
    }
}

IMPLEMENT_REGEN_FUNCTIONS(gcmp, SectionViewSymbolNew, ModelViewRangeUpdated)

DBOBJECT_DATA_DEFINE(SectionViewSymbolNew)
{
    m_pOwnerElement = nullptr;
    SetSectionModelViewId__(ElementId::InvalidID);
    SetMarkChanged__(true);
}

ISectionViewSymbolNew* SectionViewSymbolNew::Create(IDocument* pDoc, ElementId sectionModelViewId, const Coordinate3d& sectionViewCoord)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(sectionModelViewId.IsValid(), L"invalid sectionModelViewId",L"GDMPLab",L"2024-03-30");
    OwnerPtr<SectionViewSymbolNew> opSymbol = NEW_AS_OWNER_PTR(SectionViewSymbolNew);
    SectionViewSymbolNew* pSymbol = opSymbol.get();

    IGenericElement* pGenericElement = IGenericElement::Create(pDoc, TransferOwnership(opSymbol), SectionViewSymbolNew::GetClassId().GetGuid());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement, L"invalid pGenericElement",L"GDMPLab",L"2024-03-30");

    pGenericElement->SetPositionPoints(NEW_AS_OWNER_PTR(SectionViewSymbolNewPositionPoints, pGenericElement));
    if (pGenericElement->GetElementParameters())
        pGenericElement->GetElementParameters()->SetElementParametersCustomizer(NEW_AS_OWNER_PTR(SectionViewSymbolNewParametersCustomizer));
    pGenericElement->SetElementTransformationComponent(NEW_AS_OWNER_PTR(SectionViewSymbolNewTransformationComponent));
    pGenericElement->SetViewSpecificShapeComponent(NEW_AS_OWNER_PTR(SectionViewSymbolNewViewSpecificShapeComponent));
    pGenericElement->SetElementCopyStrategyComponent(NEW_AS_OWNER_PTR(SectionViewSymbolNewCopyStrategyComponent));
    pGenericElement->SetElementCopyPasteComponent(NEW_AS_OWNER_PTR(SectionViewSymbolNewCopyPasteComponent));

    pGenericElement->SetElementRegenerationComponent(NEW_AS_OWNER_PTR(SectionViewSymbolNewRegenerationBehavior));
    IElementBasicInformation* pBasicInfo = pGenericElement->GetBasicInformation();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBasicInfo, L"invalid pBasicInfo",L"GDMPLab",L"2024-03-30");
    pBasicInfo->SetCategoryUid(BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
    pBasicInfo->SetDefaultTypeName(GBMP_TR(L"剖面视图"));
    pBasicInfo->SetImplementationUid(SectionViewSymbolNew::GetImplementationUid());

    pSymbol->SetSectionModelViewId(sectionModelViewId);
    pSymbol->SetSectionViewCoord__(sectionViewCoord);

    IModelView* pSectionModelView = quick_cast<IModelView>(pDoc->GetElement(sectionModelViewId));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSectionModelView, L"invalid pSectionModelView",L"GDMPLab",L"2024-03-30");
    IViewClipRange* pViewClipRange = IViewClipRange::GetViewClipRange(pSectionModelView->GetDocument(), pSectionModelView->GetViewClipRangeId());
    pSectionModelView->SetViewSymbolId(pGenericElement->GetElementId());
    {
        //使用视口范围初始化视图标记控制点（非剖切盒）的位置
        double leftOffset = 0;
        double rightOffset = 0;
        double upOffset = 0;
        double downOffset = 0;
        pViewClipRange->GetRectViewClipRange(leftOffset, rightOffset, upOffset, downOffset);
        pSymbol->SetSymbolLeftPtOffset__(leftOffset);
        pSymbol->SetSymbolRightPtOffset__(rightOffset);
        pSymbol->SetSymbolUpPtOffset__(upOffset);
        pSymbol->SetSymbolDownPtOffset__(downOffset);
    }

    // 转发视图参数行为
    IElementParameters* pGenericElementParameters = pGenericElement->GetElementParameters();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElementParameters, L"invalid pGenericElementParameters",L"GDMPLab",L"2024-03-30");
    pGenericElementParameters->AddIndividualParameterOverride(NEW_AS_OWNER_PTR(SectionViewSymbolNewNameParameterOverride, pGenericElement));
    pGenericElementParameters->AddIndividualParameterOverride(NEW_AS_OWNER_PTR(SectionViewSymbolNewTopPlaneOffsetParameterOverride, pGenericElement));

    return quick_cast<ISectionViewSymbolNew>(pGenericElement->GetExternalObject());
}

#pragma region IExternalObject 接口
bool SectionViewSymbolNew::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

const IElement* SectionViewSymbolNew::GetOwnerElement() const
{
    return m_pOwnerElement;
}

IElement* SectionViewSymbolNew::GetOwnerElement()
{
    return m_pOwnerElement;
}

NdbObject* SectionViewSymbolNew::GetTopOwnerObject() const
{
    return quick_cast<NdbObject>(const_cast<IElement*>(GetOwnerElement()));
}

void SectionViewSymbolNew::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
}

void SectionViewSymbolNew::ReportParents(IElementParentReporter& reporter) const
{
    reporter.ReportStrong(GetModelViewId());
}

bool SectionViewSymbolNew::FinishEditing()
{
    return true;
}
#pragma endregion IExternalObject 接口

#pragma region ISectionViewSymbolNew 接口
ElementId SectionViewSymbolNew::GetModelViewId() const
{
    return GetSectionModelViewId__();
}

ElementId SectionViewSymbolNew::GetOwnerElementId() const
{
    if (!m_pOwnerElement)
    {
        return ElementId::InvalidID;
    }
    return m_pOwnerElement->GetElementId();
}

#pragma endregion ISectionViewSymbolNew 接口

#pragma region 其他
OwnerPtr<IGraphicsElementShape> SectionViewSymbolNew::CreateModelViewElementShape(const GbmpSectionViewInput& sectionViewInput, const IModelView* pModelView)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"invalid pModelView",L"GDMPLab",L"2024-03-30");
    //剖面视图各方向向量
    Vector3d sectionViewPoint = sectionViewInput.Origin;
    Vector3d sectionViewDir = sectionViewInput.ViewDirection;
    Vector3d sectionViewRightDir = sectionViewInput.RightDirection;
    Vector3d sectionViewUpDir = sectionViewInput.UpDirection;
    sectionViewDir.Normalize();
    sectionViewRightDir.Normalize();
    sectionViewUpDir.Normalize();

    double leftOffset = sectionViewInput.SymbolLeftPtOffset;
    double rightOffset = sectionViewInput.SymbolRightPtOffset;
    double upOffset = sectionViewInput.SymbolUpPtOffset;
    double downOffset = sectionViewInput.SymbolDownPtOffset;

    std::wstring symbolName = sectionViewInput.Name;

    //ViewSpecificShape 所在的平面(workPlane)的各方向向量
    Vector3d workPlaneRightDir = pModelView->GetRightDirection();
    Vector3d workPlaneUpDir = pModelView->GetUpDirection();
    Vector3d workPlaneViewDir = pModelView->GetViewDirection();
    workPlaneRightDir.Normalize();
    workPlaneUpDir.Normalize();
    workPlaneViewDir.Normalize();

    //获取剖面视图视点在workPlane上的投影点
    OwnerPtr<IPlane> opWorkPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opWorkPlane, L"invalid opWorkPlane",L"GDMPLab",L"2024-03-30");
    Vector3d sectionViewPointProjected;
    Vector2d uvParameter;
    AlgorithmProject::Project(sectionViewPoint, opWorkPlane.get(), uvParameter, sectionViewPointProjected);

    //获取剖面视图方向在workPlane上的投影向量
    Vector3d tempSectionViewPointProjected;
    AlgorithmProject::Project(sectionViewPoint + sectionViewDir, opWorkPlane.get(), uvParameter, tempSectionViewPointProjected);
    Vector3d sectionViewDirProjected = tempSectionViewPointProjected - sectionViewPointProjected;
    sectionViewDirProjected.Normalize();

    //获取Doc
    IDocument* pDoc = sectionViewInput.Document;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IGraphicsElementShape> opGrep = IGraphicsElementShape::Create(GraphicsRenderLayer::Annotation);

    auto AddSymbolText = [&symbolName, &opGrep, &sectionViewDirProjected, &workPlaneRightDir, &workPlaneViewDir, pDoc]
    (const Vector3d& firstPointPos, const Vector3d& secondPointPos, const UniIdentity& categoryId)->void
    {
        // 字体高度
        float fFontHeight = (float)SectionViewSymbolNewFontsHeight;

        // 剖面标记在平面水平/非水平时文字锚点位置、锚点类型、文字走向
        Vector3d firstPointViewNamePos;
        Vector3d secondPointViewNamePos;
        Vector3d textDir;
        AnchorAlignmentType textAnchorType;
        if (Vector3dUtils::IsParallel(workPlaneRightDir, firstPointPos - secondPointPos))
        {
            textDir = workPlaneRightDir;
            textAnchorType = AnchorAlignmentType::Center;
            firstPointViewNamePos = firstPointPos + sectionViewDirProjected * (SectionViewSymbolShortLineLength * 2.0);
            secondPointViewNamePos = secondPointPos + sectionViewDirProjected * (SectionViewSymbolShortLineLength * 2.0);
        }
        else
        {
            textDir = sectionViewDirProjected;
            textAnchorType = AnchorAlignmentType::LeftCenter;
            firstPointViewNamePos = firstPointPos + sectionViewDirProjected * (SectionViewSymbolShortLineLength * 1.5);
            secondPointViewNamePos = secondPointPos + sectionViewDirProjected * (SectionViewSymbolShortLineLength * 1.5);
        }

        OwnerPtr<IGraphicsText> opLeftNameText = IGraphicsText::Create(L"", firstPointViewNamePos, textDir, -workPlaneViewDir, fFontHeight, symbolName.c_str(), textAnchorType);
        OwnerPtr<IGraphicsText> oprightNameText = IGraphicsText::Create(L"", secondPointViewNamePos, textDir, -workPlaneViewDir, fFontHeight, symbolName.c_str(), textAnchorType);
        opLeftNameText->SetTextPrimitiveType(TextPrimitiveType::Triangle);
        oprightNameText->SetTextPrimitiveType(TextPrimitiveType::Triangle);
        IGraphicsStyleManager* pStyleManager = pDoc->GetGraphicsStyleManager();
        if (pStyleManager)
        {
            opLeftNameText->SetGraphicsStyleId(pStyleManager->GetGraphicsStyleIdByCategoryUid(categoryId));
            oprightNameText->SetGraphicsStyleId(pStyleManager->GetGraphicsStyleIdByCategoryUid(categoryId));
            opGrep->AddChild(TransferOwnership(opLeftNameText));
            opGrep->AddChild(TransferOwnership(oprightNameText));
        }
    };

    auto AddSymbolLine = [&opGrep, pDoc](const Vector3d& firstPointPos, const Vector3d& secondPointPos, const UniIdentity& categoryId)->void
    {
        OwnerPtr<IGraphicsLine> symbolLine = IGraphicsLine::Create(firstPointPos, secondPointPos);
        IGraphicsStyleManager* pStyleManager = pDoc->GetGraphicsStyleManager();
        if (pStyleManager)
        {
            symbolLine->SetGraphicsStyleId(pStyleManager->GetGraphicsStyleIdByCategoryUid(categoryId));
            opGrep->AddChild(TransferOwnership(symbolLine));
        }
    };

    //workPlane为与剖切盒上下表面平行的面
    if (GbmpModelViewUtil::IsModelViewPlaneParallelToSectionBoxUpDownPlane(workPlaneViewDir, sectionViewDir, sectionViewUpDir))
    {
        Vector3d leftPoint = sectionViewPointProjected + (Vector3dUtils::RotateVectorAroundAxis(sectionViewDirProjected, -workPlaneViewDir, Constants::MATH_PI_2)) * leftOffset;
        Vector3d rightPoint = sectionViewPointProjected + (Vector3dUtils::RotateVectorAroundAxis(sectionViewDirProjected, -workPlaneViewDir, -Constants::MATH_PI_2)) * rightOffset;
        Vector3d leftToRightDir = rightPoint - leftPoint;
        leftToRightDir.Normalize();

        //左端点的两条剖面符号线
        AddSymbolLine(leftPoint, leftPoint + sectionViewDirProjected * SectionViewSymbolShortLineLength, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
        AddSymbolLine(leftPoint, leftPoint + leftToRightDir * SectionViewSymbolLongLineLength, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
        //右端点的两条剖面符号线
        AddSymbolLine(rightPoint, rightPoint + sectionViewDirProjected * SectionViewSymbolShortLineLength, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
        AddSymbolLine(rightPoint, rightPoint + (-leftToRightDir) * SectionViewSymbolLongLineLength, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
        //剖面符号中间连线
        AddSymbolLine(leftPoint, rightPoint, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL_LINE);
        //文字
        AddSymbolText(leftPoint, rightPoint, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
    }
    //workPlane为与剖切盒左右表面平行的面
    else if (GbmpModelViewUtil::IsModelViewPlaneParallelToSectionBoxLeftRightPlane(workPlaneViewDir, sectionViewDir, sectionViewUpDir))
    {
        Vector3d upPoint = sectionViewPointProjected + sectionViewUpDir * upOffset;
        Vector3d downPoint = sectionViewPointProjected + (-sectionViewUpDir) * downOffset;
        Vector3d upToDownDir = downPoint - upPoint;
        upToDownDir.Normalize();

        //上端点的两条剖面符号线
        AddSymbolLine(upPoint, upPoint + upToDownDir * SectionViewSymbolLongLineLength, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
        AddSymbolLine(upPoint, upPoint + sectionViewDirProjected * SectionViewSymbolShortLineLength, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
        //下端点的两条剖面符号线
        AddSymbolLine(downPoint, downPoint + (-upToDownDir) * SectionViewSymbolLongLineLength, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
        AddSymbolLine(downPoint, downPoint + sectionViewDirProjected * SectionViewSymbolShortLineLength, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
        //剖面符号中间连线
        AddSymbolLine(upPoint, downPoint, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL_LINE);
        //文字
        AddSymbolText(upPoint, downPoint, BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
    }
    opGrep->SetIsClippable(false);
    return TransferOwnership(opGrep);
}

gcmp::UniIdentity gcmp::SectionViewSymbolNew::GetImplementationUid()
{
    static UniIdentity s_implementationUid = UniIdentity::Create(
        GuidUtils::FromString(L"{9310C3E4-5C5D-4CD6-BCE1-2BC5D53C58D5}"), L"SectionViewSymbolNew");
    return s_implementationUid;
}

const gcmp::Coordinate3d& gcmp::SectionViewSymbolNew::GetSectionViewCoord() const
{
    return GetSectionViewCoord__();
}

void gcmp::SectionViewSymbolNew::SetSectionViewCoord(const Coordinate3d& sectionViewCoord)
{
    SetSectionViewCoord__(sectionViewCoord);
    MarkSectionViewCoordRdId();
}

OwnerPtr<IGraphicsElementShape> SectionViewSymbolNew::CreateModelViewElementShape(const IModelView* pModelView) const
{
    IModelView* pSectionModelView = GetSectionModelView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSectionModelView, L"invalid pSectionModelView",L"GDMPLab",L"2024-03-30");
    IViewClipRange* pViewClipRange = IViewClipRange::GetViewClipRange(pSectionModelView->GetDocument(), pSectionModelView->GetViewClipRangeId());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pViewClipRange, L"invalid pViewClipRange",L"GDMPLab",L"2024-03-30");

    double leftOffset = 0;
    double rightOffset = 0;
    double upOffset = 0;
    double downOffset = 0;
    pViewClipRange->GetRectViewClipRange(leftOffset, rightOffset, upOffset, downOffset);

    GbmpSectionViewInput input;
    input.Origin = pSectionModelView->GetOrigin();
    input.ViewDirection = pSectionModelView->GetViewDirection();
    input.RightDirection = pSectionModelView->GetRightDirection();
    input.UpDirection = pSectionModelView->GetUpDirection();
    input.RectViewportWidth = leftOffset + rightOffset;
    input.RectViewportHeight = upOffset + downOffset;
    input.SymbolLeftPtOffset = GetSymbolLeftPtOffset();
    input.SymbolRightPtOffset = GetSymbolRightPtOffset();
    input.SymbolUpPtOffset = GetSymbolUpPtOffset();
    input.SymbolDownPtOffset = GetSymbolDownPtOffset();
    input.Name = pSectionModelView->GetName();
    input.Document = GetDocument();

    return SectionViewSymbolNew::CreateModelViewElementShape(input, pModelView);
}

bool SectionViewSymbolNew::MakeTransform(const Matrix4d& matrix)
{
    IModelView* pSectionModelView = GetSectionModelView();

    Vector3d viewOrigin = pSectionModelView->GetOrigin();
    Vector3d viewDirection = pSectionModelView->GetViewDirection();
    Vector3d upDirection = pSectionModelView->GetUpDirection();
    Vector3d rightDirection = pSectionModelView->GetRightDirection();
    double bottomOffset(0.0);
    pSectionModelView->GetBottomPlaneOffset(bottomOffset);

    // 变换引用ModelView坐标系
    {
        Vector3d viewXDir = upDirection.Cross(viewDirection); //确保法向和上方向正确
        Coordinate3d modelViewCoord(viewOrigin, viewXDir, upDirection, viewDirection);
        modelViewCoord.Transform(matrix);

        Vector3d newOrigin = modelViewCoord.GetOrigin();
        Vector3d newViewDir = modelViewCoord.GetZ();
        Vector3d newViewUp = modelViewCoord.GetY();
        //这里实际上方向错了，但是改正确后引起脚本【view\AT_view_23574_模型线在编辑模式中不被裁剪】不过，暂时改回原来的错误算式
        Vector3d newViewRight = newViewUp.Cross(newViewDir);

        pSectionModelView->SetOrigin(newOrigin);
        pSectionModelView->SetViewDirection(newViewDir);
        pSectionModelView->SetUpDirection(newViewUp);
        pSectionModelView->SetRightDirection(newViewRight);


        //更新剖切试图定位坐标系
        Vector3d newCoordOriginPt = (newOrigin*newViewDir)*newViewDir;
        Matrix3d rotateMat = matrix.GetRotation();
        Vector3d oldCoordOriginPt = m_SectionViewCoord.GetOrigin();
        Vector3d translation = newCoordOriginPt - oldCoordOriginPt;
        if (!rotateMat.IsIdentity() || translation.Length() > Constants::DOUBLE_EPS)
        {
            m_SectionViewCoord.Transform(matrix);
            Coordinate3d newCoord = Coordinate3d(newCoordOriginPt,m_SectionViewCoord.GetX(),m_SectionViewCoord.GetY());
            SetSectionViewCoord(newCoord);
        }
    }

    // 更新剖切面
    pSectionModelView->DeleteTopPlane();
    pSectionModelView->AddTopPlane(0.0, true); //切面视图使用顶面支持剖切达到剖切效果

    // 更新深度面
    pSectionModelView->DeleteBottomPlane();
    pSectionModelView->AddBottomPlane(bottomOffset, true);

    //更改标志位以触发视图刷新
    MarkChanged();

    return true;
}

void SectionViewSymbolNew::MarkChanged()
{
    SetMarkChanged__(!GetMarkChanged__());
}

IDocument* SectionViewSymbolNew::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

IModelView* SectionViewSymbolNew::GetSectionModelView() const
{
    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    return quick_cast<IModelView>(pDoc->GetElement(GetSectionModelViewId__()));
}

#pragma endregion 其他

void SectionViewSymbolNew::SetSectionModelViewId(const ElementId& viewId)
{
    SetSectionModelViewId__(viewId);
    SubscribeModelViewEvent();
}

bool SectionViewSymbolNew::SubscribeModelViewEvent()
{
    IModelView* pModelView = GetSectionModelView();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"invalid pModelView",L"GDMPLab",L"2024-03-30");

    OwnerPtr<AssociatedModelViewEventHandler> opModelViewEventHandler = NEW_AS_OWNER_PTR(AssociatedModelViewEventHandler, this);
    pModelView->GetModelViewEvent()->Add(opModelViewEventHandler.get());
    SetModelViewEventHandler__(TransferOwnership(opModelViewEventHandler));

    return true;
}

bool SectionViewSymbolNew::UnsubscribeModelViewEvent()
{
    IModelView* pModelView = GetSectionModelView();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"invalid pModelView",L"GDMPLab",L"2024-03-30");

    if (pModelView)
    {
        pModelView->GetModelViewEvent()->Delete(this->GetModelViewEventHandlerFW__().get());
    }

    return true;
}

double SectionViewSymbolNew::GetSymbolLeftPtOffset() const
{
    return GetSymbolLeftPtOffset__();
}
void SectionViewSymbolNew::SetSymbolLeftPtOffset(double offset)
{
    SetSymbolLeftPtOffset__(offset);
    MarkChanged();
}
double SectionViewSymbolNew::GetSymbolRightPtOffset() const
{
    return GetSymbolRightPtOffset__();
}
void SectionViewSymbolNew::SetSymbolRightPtOffset(double offset)
{
    SetSymbolRightPtOffset__(offset);
    MarkChanged();
}
double SectionViewSymbolNew::GetSymbolUpPtOffset() const
{
    return GetSymbolUpPtOffset__();
}
void SectionViewSymbolNew::SetSymbolUpPtOffset(double offset)
{
    SetSymbolUpPtOffset__(offset);
    MarkChanged();
}
double SectionViewSymbolNew::GetSymbolDownPtOffset() const
{
    return GetSymbolDownPtOffset__();
}
void SectionViewSymbolNew::SetSymbolDownPtOffset(double offset)
{
    SetSymbolDownPtOffset__(offset);
    MarkChanged();
}

REGISTER_IMPLEMENTATION_UID_TREE_RELATION(IGenericElement, SectionViewSymbolNew);

